// =====================================================================================
// 
//       Filename:  window.h
// 
//    Description:  Interface graphique du logiciel
// 
//        Version:  1.0
//        Created:  24/06/2009 21:29:45
//       Revision:  none
//       Compiler:  g++
// 
//         Author:  François Hissel (fh), francois.hissel@m4x.org
//        Company:  
// 
// =====================================================================================


#ifndef  WINDOW_H_INC
#define  WINDOW_H_INC

#include	<gtkmm/main.h>
#include	<gtkmm/eventbox.h>
#include	<gtkmm/window.h>
#include	<gtkmm/drawingarea.h>
#include	<gtkmm/box.h>
#include	<gtkmm/button.h>
#include	<gtkmm/entry.h>
#include	<gtkmm/label.h>
#include	<gtkmm/frame.h>
#include	<gtkmm/checkbutton.h>
#include	"application.h"

class Fenetre;

/**
 * \class Zone
 * \brief Zone de tracé dans la fenêtre courante
 *
 * La classe représente la zone de tracé. Elle utilise la bibliothèque de dessin Cairo, et contient des références vers le réseau routier et l'ensemble des caractéristiques à représenter (itinéraire, frontière du domaine)
 */
class Zone:public Gtk::DrawingArea {
	friend class Fenetre;
	public:

		/**
		 * \brief Constructeur standard
		 *
		 * Le constructeur initialise la zone en connectant les signaux aux méthodes qui les implémentent
		 */
		Zone(Fenetre *f);
		virtual ~Zone();	//!< Destructeur standard
	protected:

		/**
		 * \brief Fonction de tracé du dessin
		 *
		 * La fonction représente la carte du lieu. Elle est appelée à chaque fois qu'un tracé, total ou partiel, est nécessaire.
		 * \param event Caractéristiques de l'événement qui est à l'origine de la demande de rafraîchissement du tracé
		 */
		virtual bool on_expose_event(GdkEventExpose *event);
	private:
		Fenetre *fenetre;	//!< Fenêtre principale de l'application

		/**
		 * \brief Mode dans lequel l'application se situe
		 *
		 * Mode indique le mode dans lequel l'application se situe, et définit sa façon de réagir aux événements. Les valeurs possibles sont les suivantes :
		 * 	- 0 : L'application ne réagit pas lorsque l'utilisateur clique sur la zone de dessin.
		 * 	- 1 : L'utilisateur est en train de choisir le point de départ de son itinéraire. S'il clique sur la zone de dessin, le point de départ est initialisé au noeud le plus proche du point où il a cliqué.
		 * 	- 2 : L'utilisateur est en train de choisir le point d'arrivée de son itinéraire. S'il clique sur la zone de dessin, le point d'arrivée est initialisé au noeud le plus proche du point où il a cliqué.
		 * 	- 5 : L'utilisateur place une nouvelle source sur la carte
		 */
		int mode;
		bool def_deb;	//!< Indique si le point de départ de l'itinéraire a été défini
		double x_deb;	//!< Abscisse du point de départ de l'itinéraire à composer
		double y_deb;	//!< Ordonnée du point de départ de l'itinéraire à composer
		bool def_fin;	//!< Indique si le point d'arrivée de l'itinéraire a été défini
		double x_fin;	//!< Abscisse du point d'arrivée de l'itinéraire à composer
		double y_fin;	//!< Ordonnée du point d'arrivée de l'itinéraire à composer
		int width;	//!< Largeur sur l'écran de la fenêtre
		int height;	//!< Hauteur sur l'écran de la fenêtre
		int dessine_raster;	//!< Indique le numéro de la carte raster à tracer, 1 pour la carte d'accessibilité, 2 pour la carte de desserte, 0 si aucune carte ne doit être recalculée

		/**
		 * \brief Tracé de la carte raster
		 *
		 * La méthode trace la carte raster contenue dans la zone sur le contexte Cairo spécifié en argument. Si la zone ne contient aucune carte raster, l'appel à la fonction n'aura aucun effet.
		 * \param cr Contexte sur lequel la carte sera tracée
		 */
		void trace_raster(Cairo::RefPtr<Cairo::Context> cr);

		/**
		 * \brief Invalide la carte raster en mémoire
		 *
		 * La méthode rend invalide la carte raster stockée en mémoire. Cela a pour effet de libérer les ressources mémoires associées et de supprimer son tracé.
		 */
		void invalide_raster();
};

/**
 * \class Fenetre
 * \brief Fenêtre principale de l'application
 *
 * La classe représente la fenêtre principale de l'application à laquelle sont associés tous les composants et tous les événements.
 * Elle hérite à la fois de la classe fenêtre de Gtk qui lui permet de représenter les composants graphiques, et de la classe Application qui lui fournit les méthodes pour traiter les calculs sur le réseau
 */
class Fenetre:public Gtk::Window {
	public:
		Application* app;	//!< Pointeur vers l'application associée à la fenêtre
		Zone *zone;	//!< Zone de dessin
		Gtk::EventBox zone_events;	//!< Fenêtre X fictive pour la capture des événements de souris sur la zone de dessin
		Gtk::HBox sep;	//!< Séparateur horizontal de zones
		Gtk::VBox sep2;	//!< Séparateur vertical de zones de la barre des boutons
		Gtk::HBox sep3;	//!< Séparateur pour la zone d'entrée du poids
		Gtk::VBox sep4;	//!< Séparateur pour le groupe de sélection de la carte raster à afficher
		Gtk::Button btnInit;	//!< Bouton de choix du point de départ
		Gtk::Button btnFin;	//!< Bouton de choix du point d'arrivée
		Gtk::Button btnRecalculer;	//!< Bouton de lancer du calcul du nouvel itinéraire
		Gtk::Label labelNiveau;	//!< Label de la zone de texte pour le choix d'un niveau d'eau
		Gtk::Entry textNiveau;	//!< Zone de texte permettant le choix d'un niveau d'eau
		Gtk::Button btnCalculerPoids;	//!< Bouton de mise à jour des poids des tronçons en fonction du niveau d'eau choisi
		Gtk::Button btnSources;	//!< Bouton de choix des positions sources
		Gtk::Button btnVideSources;	//!< Bouton de suppression des positions sources
		Gtk::Button btnEnjeux;	//!< Bouton de choix des positions des enjeux
		Gtk::Button btnVideEnjeux;	//!< Bouton de suppression des positions d'enjeux
		Gtk::Button btnTournee;	//!< Bouton de calcul de la tournée optimale
		Gtk::Frame frameRaster;	//!< Groupe de sélection de la carte raster à afficher
		Gtk::CheckButton btnAccessibilite;	//!< Bouton de tracé de l'accessibilité
		Gtk::CheckButton btnDesserte;	//!< Bouton de tracé de la desserte
		Gtk::Button btnQuitter;	//!< Bouton de sortie du programme

		/**
		 * \brief Constructeur principale d'une structure Fenetre
		 *
		 * La méthode construit la structure de fenêtre et l'associé à l'application spécifiée en paramètre. Toutes les opérations réalisées dans l'interface seront reportées dans l'application sous-jacente.
		 * \param papp Application associée à la fenêtre
		 */
		Fenetre(Application* papp);

		virtual ~Fenetre();	//!< Destructeur standard
		void btnQuitter_click_event(); //!< Action réalisée lorsque l'utilisateur clique sur le bouton "Quitter"
		void btnInit_click_event();	//!< Action réalisée lorsque l'utilisateur clique sur le bouton "Placer le départ"
		void btnFin_click_event();	//!< Action réalisée lorsque l'utilisateur clique sur le bouton "Placer l'arrivée"
		void btnRecalculer_click_event();	//!< Action réalisée lorsque l'utilisateur clique sur le bouton "Itinéraire"
		void btnSources_click_event();	//!< Action réalisée lorsque l'utilisateur clique sur le bouton "Placer les sources"
		void btnVideSources_click_event();	//!< Action réalisée lorsque l'utilisateur clique sur le bouton "Enlever les sources"
		void btnEnjeux_click_event();	//!< Action réalisée lorsque l'utilisateur clique sur le bouton "Placer les enjeux"
		void btnVideEnjeux_click_event();	//!< Action réalisée lorsque l'utilisateur clique sur le bouton "Enlever les enjeux"
		void btnTournee_click_event();	//!< Action réalisée lorsque l'utilisateur clique sur le bouton "Calculer la tournée"
		void btnCalculerPoids_click_event();	//!< Action réalisée lorsque l'utilisateur clique sur le bouton "Recalculer les poids"
		void btnAccessibilite_click_event();	//!< Action réalisée lorsque l'utilisateur clique sur le bouton "Accessibilité"
		void btnDesserte_click_event();	//!< Action réalisée lorsque l'utilisateur clique sur le bouton "Desserte"

		/**
		 * \brief Fonction appelée lorsque l'utilisateur clique sur la zone de dessin
		 *
		 * La fonction est appelée lorsque l'utilisateur clique sur la zone de dessin. La commande est capturée via une fenêtre X fictive située au-dessus de cette zone. L'action réalisée dépend de la variable mode, qui indique comment le composant doit réagir à la demande de l'utilisateur.
		 */
		virtual bool on_button_press_event(GdkEventButton *event);

		/**
		 * \brief Affiche un message à destination de l'utilisateur
		 *
		 * La fonction ouvre une fenêtre d'information dont le logo est déterminé par le paramètre type et affiche le message spécifié en premier argument. Si un titre est spécifié, il apparaît au début du message en emphase. L'exécution de l'application ne se poursuit qu'après que l'utilisateur ait fermé la fenêtre de dialogue.
		 * \param message Message à afficher
		 * \param type Code représentant le type du message
		 * \param titre Titre du message, nul par défaut
		 */
		static void affiche(const string &message,MessageType type,const string &titre="");

		/**
		 * \brief Affiche un message d'erreur
		 *
		 * La fonction affiche le message spécifié en premier argument sur le flux de sortie d'erreur.
		 * \param message Message à afficher
		 * \param type Code représentant le type du message
		 * \param titre Titre du message, nul par défaut
		 */
		static void affiche_erreur(const string &message,MessageType type,const string &titre="");
};

/* 
 * \fn void openWindow(Application *papp)
 * \brief Ouvre la fenêtre graphique et construit la zone de dessin
 *
 * La fonction ouvre la fenêtre graphique, la maximise et y associe la fenêtre de dessin pour le réseau contenu dans l'application papp.
 * L'ouverture de la fenêtre graphique nécessite d'avoir défini les facteurs de zoom, les cartes vectorielles d'entrée, et d'avoir importé ces données dans papp.
 * Enfin, la méthode lit les arguments de la ligne de commande transmis via Application::argc et Application::argv, et y repère les commandes de configuration classique du serveur X, qui sont alors interprétées et peuvent modifier l'apparence de l'interface.
 * \param papp Application liée à la fenêtre
 */
void openWindow(Application *papp);

#endif   // ----- #ifndef WINDOW_H_INC  -----
